package home.control.service;

import home.control.AlarmActivity;
import home.control.data.IGetData;
import home.control.logicElements.Action;
import home.control.logicElements.ActionTypes;
import home.control.logicElements.HomeParts;
import home.control.logicElements.Plan;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;

import com.managment.alarm.AlarmStatus;
import com.managment.alarm.CheckAlarm;
import com.managment.data.Media;
import com.managment.data.Task;
import com.managment.functions.activate.ActivateProfile;
import com.managment.functions.activate.ActivationFailed;
import com.managment.functions.activate.ProfileActivated;
import com.managment.functions.add.AddFailed;
import com.managment.functions.add.AddProfile;
import com.managment.functions.add.AddTask;
import com.managment.functions.add.ProfileAdded;
import com.managment.functions.add.TaskAdded;
import com.managment.functions.check.CheckMedia;
import com.managment.functions.check.MediaState;
import com.managment.functions.get.GetFailed;
import com.managment.functions.get.GetProfiles;
import com.managment.functions.get.Profiles;
import com.managment.functions.update.ProfileUpdated;
import com.managment.functions.update.UpdateFailed;
import com.managment.functions.update.UpdateProfile;

import communication.account.login.Login;
import communication.account.login.LoginAccomplished;
import communication.account.login.LoginFailed;

public class GetData implements IGetData {
	private static final String TAG = "GetData";
	private ServerAdapter sa;
	
	private boolean cantCheckAlarm = false;

	private ObjectOutputStream os;
	private ObjectInputStream is;
	
	private boolean stopThread = false;
	
	private static GetData reference;
	
	public static GetData getInstance(){
		if(reference == null){
			reference =  new GetData();
			return reference;
		}else{
			return reference;
		}
	}

	private GetData() {
	}
	
	public boolean getAlarm() {
		if(cantCheckAlarm){
			Log.d("Alarm", "Nie moge sprawdzic alarmu");
			return false;
		}
		Log.d("Alarm", "Moge sprawdzic alarma");
		Object o = null;
		CheckAlarm ca = new CheckAlarm();
		AlarmStatus as = null;
		
		try {
			Log.v(TAG, "--> CheckAlarm sent");
			os.writeObject(ca);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + " received");
			if (o instanceof AlarmStatus) {
				as = (AlarmStatus)o;
				if(as.getStatus().equals("true")){
					cantCheckAlarm = false;
					return true;
				}
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
		return false;
	}

	public boolean login(String host, String pass) {
		cantCheckAlarm = true;
		sa = new ServerAdapter(host);
		sa.connectToServer();
		os = sa.getObjectOutputStream();
		is = sa.getObjectInputStream();

		Login l = new Login();
		Object o = null;
		l.setPassword(pass);

		try {
			os.writeObject(l);
			os.flush();
			o = is.readObject();
			if (o instanceof LoginAccomplished) {
				cantCheckAlarm = false;
				return true;
			} else if (o instanceof LoginFailed) {
				cantCheckAlarm = false;
				return false;
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (NullPointerException e ){
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
		return false;
	}

	@Override
	public void add(Plan selectedItem, Action action) {
		cantCheckAlarm = true;
		Object o = null;
		UpdateProfile up = new UpdateProfile();
		up.setOldProfile(selectedItem.getName());
		Plan newPlan = selectedItem;
		newPlan.addAction(action);
		up.setNewProfile(Converter.planToProfile(newPlan));
		
		UpdateFailed uf = null;
		ProfileUpdated pu = null;
		
		try {
			Log.v(TAG, "--> UpdateProfile sent");
			os.writeObject(up);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof ProfileUpdated) {
				pu = (ProfileUpdated)o;
				//Log.v(TAG, pu.getMessage());
			} else if (o instanceof UpdateFailed) {
				uf = (UpdateFailed)o;
				Log.e(TAG, uf.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
	}

	@Override
	public void addPlan(Plan p) {
		cantCheckAlarm = true;
		Object o = null;
		AddProfile ap = new AddProfile();
		ap.setProfile(Converter.planToProfile(p));
		AddFailed af = null;
		ProfileAdded pa = null;
		
		try {
			Log.v(TAG, "--> AddProfile sent");
			os.writeObject(ap);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof ProfileAdded) {
				pa = (ProfileAdded)o;
				//Log.v(TAG, pa.getMessage());
			} else if (o instanceof AddFailed) {
				af = (AddFailed)o;
				Log.e(TAG, af.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
	}

	@Override
	public boolean checkStatus(HomeParts homePart) {
		cantCheckAlarm = true;
		Object o = null;
		CheckMedia cm = new CheckMedia();
		cm.setMedia(Converter.homePartsToMedia(homePart));
		MediaState ms = null;
		
		try {
			Log.v(TAG, "--> CheckMedia sent");
			os.writeObject(cm);
			Log.v(TAG, "Flush");
			os.flush();
			Log.v(TAG, "po flushu");
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + " received"); 
			if (o instanceof MediaState) {
				ms = (MediaState)o;
				if(ms.getState().equals("on")){
					cantCheckAlarm = false;
					return true;
				}
			} 
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
		return false;
	}

	@Override
	public List<Plan> getAllPlans() {
		cantCheckAlarm = true;
		GetProfiles gp = new GetProfiles();
		Object o = null;
		Profiles p = null;
		GetFailed gf = null;

		try {
			Log.v(TAG, "--> GetProfiles sent");
			if(os == null){
				Log.v(TAG, "os jest null");
			}
			os.writeObject(gp);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof Profiles) {
				p = (Profiles)o;
				return Converter.profileListToPlanList(p.getProfiles());
			} else if (o instanceof GetFailed) {
				gf = (GetFailed)o;
				Log.e(TAG, gf.getMessage());
				cantCheckAlarm = false;
				return null;
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
		return null;
	}

	@Override
	public List<HomeParts> getInstantActions() {
		cantCheckAlarm = true;
		List<HomeParts> hp = new ArrayList<HomeParts>();
		hp.add(HomeParts.ALL_HOUSE);
		hp.add(HomeParts.BATHROOM_LIGHTS);
		hp.add(HomeParts.KITCHEN_LIGHTS);
		hp.add(HomeParts.LIVING_LIGHTS);
		cantCheckAlarm = false;
		return hp; 
	}

	@Override
	public ActionTypes getTemperature() {
		cantCheckAlarm = true;
		Object o = null;
		CheckMedia cm = new CheckMedia();
		cm.setMedia(Media.HEATTER);
		MediaState ms = null;
		
		try {
			Log.v(TAG, "--> CheckMedia sent");
			os.writeObject(cm);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof MediaState) {
				ms = (MediaState)o;
				cantCheckAlarm = false;
				return Converter.stateToActionTypes(ms.getState());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
		return null;
	}

	@Override
	public void removeActionFromPlan(Plan selectedItem, Action action) {
		cantCheckAlarm = true;
		Object o = null;
		UpdateProfile up = new UpdateProfile();
		up.setOldProfile(selectedItem.getName());
		Plan p = selectedItem;
		p.removeAction(action);
		up.setNewProfile(Converter.planToProfile(p));
		
		UpdateFailed uf = null;
		ProfileUpdated pu = null;
		
		try {
			Log.v(TAG, "--> UpdateProfile sent");
			os.writeObject(up);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof ProfileUpdated) {
				pu = (ProfileUpdated)o;
				//Log.e(TAG, pu.getMessage());
			} else if (o instanceof UpdateFailed) {
				uf = (UpdateFailed)o;
				Log.e(TAG, uf.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
	}

	@Override
	public void setActivePlan(Plan p) {
		cantCheckAlarm = true;
		Object o = null;
		ActivateProfile ap = new ActivateProfile();
		ap.setName(p.getName());
		ActivationFailed af = null; 
		ProfileActivated pa = null;
		
		try {
			Log.v(TAG, "--> ActivateProfile sent");
			os.writeObject(ap);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof ProfileActivated) {
				pa = (ProfileActivated)o;
				//Log.v(TAG, pa.getMessage());
			} else if (o instanceof ActivationFailed) {
				af = (ActivationFailed)o;
				Log.e(TAG, af.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
	}

	@Override
	public void setStatus(HomeParts homePart, boolean isChecked) {
		cantCheckAlarm = true;
		Object o = null;
		AddTask at = new AddTask();
		
		Time eventTime = null;
		Media media = Converter.homePartsToMedia(homePart);
		String state;
		if(isChecked){
			state = "on";
		} else {
			state = "off";
		}
		Task t = new Task(media, eventTime, state);
		
		at.setTask(t);
		AddFailed af = null;
		TaskAdded ta = null;
		
		try {
			Log.v(TAG, "--> AddTask sent");
			os.writeObject(at);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof TaskAdded) {
				ta = (TaskAdded)o;
				//Log.v(TAG, ta.getMessage());
			} else if (o instanceof AddFailed) {
				af = (AddFailed)o;
				Log.e(TAG, af.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
		cantCheckAlarm = false;
	}

	@Override
	public void setTemperature(ActionTypes heatingOff) {
		cantCheckAlarm = true;
		Object o = null;
		AddTask at = new AddTask();

		Time eventTime = null;
		Media media = Media.HEATTER;
		String state = Converter.actionTypesToState(heatingOff);
		Task t = new Task(media, eventTime, state);
		
		at.setTask(t);
		AddFailed af = null;
		TaskAdded ta = null;
		
		try {
			Log.v(TAG, "--> AddTask sent");
			os.writeObject(at);
			os.flush();
			o = is.readObject();
			Log.v(TAG, "<-- " + o.getClass().getName() + "received");
			if (o instanceof TaskAdded) {
				ta = (TaskAdded)o;
				//Log.v(TAG, ta.getMessage());
			} else if (o instanceof AddFailed) {
				af = (AddFailed)o;
				Log.e(TAG, af.getMessage());
			}
		} catch (IOException e) {
			Log.e(TAG, e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			Log.e(TAG, e.getMessage(), e);
		}
	cantCheckAlarm = false;
	}
}
